package me.zhengjie.modules.quartz.rest

import io.swagger.v3.oas.annotations.media.Schema
import jakarta.servlet.http.HttpServletResponse
import me.zhengjie.common.exception.BadRequestException
import me.zhengjie.common.utils.SpringContextHolder
import me.zhengjie.logging.annotation.Log
import me.zhengjie.modules.quartz.domain.QuartzJob
import me.zhengjie.modules.quartz.service.QuartzJobService
import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria
import org.springframework.data.domain.Pageable
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*
import java.io.IOException

/**
 * @author Kuki Wu
 * @date 2019-01-07
 */
@RestController
@Schema(description="系统:定时任务管理")
@RequestMapping("/api/jobs")
class QuartzJobController(private val quartzJobService: QuartzJobService) {
    @Log("查询定时任务")
    @Schema(description = "查询定时任务")
    @GetMapping
    @PreAuthorize("@el.check('timing:list')")
    fun getJobs(criteria: JobQueryCriteria?, pageable: Pageable?): ResponseEntity<*> {
        return ResponseEntity(quartzJobService.queryAll(criteria, pageable) as Any, HttpStatus.OK)
    }

    @Log("导出任务数据")
    @Schema(description = "导出任务数据")
    @GetMapping(value = ["/download"])
    @PreAuthorize("@el.check('timing:list')")
    @Throws(
        IOException::class
    )
    fun download(response: HttpServletResponse?, criteria: JobQueryCriteria?) {
        quartzJobService.download(quartzJobService.queryAll(criteria), response)
    }

    @Log("导出日志数据")
    @Schema(description = "导出日志数据")
    @GetMapping(value = ["/download/log"])
    @PreAuthorize("@el.check('timing:list')")
    @Throws(
        IOException::class
    )
    fun downloadLog(response: HttpServletResponse?, criteria: JobQueryCriteria?) {
        quartzJobService.downloadLog(quartzJobService.queryAllLog(criteria), response)
    }

    @Schema(description = "查询任务执行日志")
    @GetMapping(value = ["/logs"])
    @PreAuthorize("@el.check('timing:list')")
    fun getJobLogs(criteria: JobQueryCriteria?, pageable: Pageable?): ResponseEntity<*> {
        return ResponseEntity(quartzJobService.queryAllLog(criteria, pageable) as Any, HttpStatus.OK)
    }

    @Log("新增定时任务")
    @Schema(description = "新增定时任务")
    @PostMapping
    @PreAuthorize("@el.check('timing:add')")
    fun create(@Validated @RequestBody resources: QuartzJob): ResponseEntity<*> {
        if (resources.id != null) {
            throw BadRequestException("A new " + ENTITY_NAME + " cannot already have an ID")
        }
        return ResponseEntity(quartzJobService.create(resources) as Any, HttpStatus.CREATED)
    }

    @Log("修改定时任务")
    @Schema(description = "修改定时任务")
    @PutMapping
    @PreAuthorize("@el.check('timing:edit')")
    fun update(
        @Validated(
            QuartzJob.Update::class
        ) @RequestBody resources: QuartzJob
    ): ResponseEntity<*> {
        quartzJobService.update(resources)
        return ResponseEntity<Any?>(HttpStatus.NO_CONTENT)
    }

    @Log("更改定时任务状态")
    @Schema(description = "更改定时任务状态")
    @PutMapping(value = ["/{id}"])
    @PreAuthorize("@el.check('timing:edit')")
    fun updateIsPause(@PathVariable id: Long): ResponseEntity<*> {
        quartzJobService.updateIsPause(quartzJobService.findById(id))
        return ResponseEntity<Any?>(HttpStatus.NO_CONTENT)
    }

    @Log("执行定时任务")
    @Schema(description = "执行定时任务")
    @PutMapping(value = ["/exec/{id}"])
    @PreAuthorize("@el.check('timing:edit')")
    fun execution(@PathVariable id: Long): ResponseEntity<*> {
        quartzJobService.execution(quartzJobService.findById(id))
        return ResponseEntity<Any?>(HttpStatus.NO_CONTENT)
    }

    @Log("删除定时任务")
    @Schema(description = "删除定时任务")
    @DeleteMapping
    @PreAuthorize("@el.check('timing:del')")
    fun deleteQuartzJob(@RequestBody ids: Set<Long?>?): ResponseEntity<Any?>? {
        quartzJobService.delete(ids!!)
        return ResponseEntity(HttpStatus.OK)
    }

    private fun checkBean(beanName: String) {
        // 避免调用攻击者可以从SpringContextHolder获得控制jdbcTemplate类
        // 并使用getDeclaredMethod调用jdbcTemplate的queryForMap函数，执行任意sql命令。
        if (!SpringContextHolder.getAllServiceBeanName()!!.contains(beanName)) {
            throw BadRequestException("非法的 Bean，请重新输入！")
        }
    }
    companion object {
        private const val ENTITY_NAME = "quartzJob"
    }

}